local gamelib = require "club.threecard.gamelib"
local slotlib = require "club.threecard.slotlib"
local components = slotlib.require "components"

local slot_system = slotlib.systems.slot_system
local class = gamelib.entitas.class
local Matcher = gamelib.entitas.Matcher
local GroupEvent = gamelib.entitas.GroupEvent
local Image = CS.UnityEngine.UI.Image

local show_result_system = class("show_result_system", slot_system)

function show_result_system:ctor(context, ingame)
    show_result_system.super.ctor(self, context, ingame);
    self.original_parent = nil;
    self.active_elements = nil;
end

function show_result_system:get_trigger()
    return {{Matcher({components.frames_component, components.auto_component, components.reel_offset_component}), GroupEvent.ADDED}};
end

function show_result_system:filter(entity)
    return entity:has(components.frames_component) and entity:has(components.auto_component) and entity:has(components.reel_offset_component)
end

local frame_type = 1;

local function filter_frame(frames)
    local ret = {}    

    for _, frame in ipairs(frames) do
        if frame.type == frame_type then
            table.insert(ret, frame);
        end
    end

    return ret;
end

local function set_box_color(color, element)
    if not element.box then
        local box = element.transform:Find("root/box");
        if not box then
            return;
        end
        box = box.gameObject:GetComponent(typeof(Image));
        if not box then
            return;
        end

        element.box = box;
    end
    element.box.color = color;

    if not element.light then
        local light = element.transform:Find("root/box/light");
        if not light then
            return;
        end

        light = light.gameObject:GetComponent(typeof(Image));
        if not light then
            return;
        end
        element.light = light;
    end

    element.light.color = color;
end

function show_result_system:execute(entitas)
    if entitas:size() ~= 1 then
        gamelib.log.error("数据错误，结果组件不可能>1")
        return;
    end

    entitas:foreach(function(e)
        local auto_component = e:get(components.auto_component);
        if auto_component and auto_component.is_auto then
            self:wait(0.5);
            return;
        end

        local frames = e:get(components.frames_component).frames;
        frames = filter_frame(frames);
        if #frames == 0 then
            return;
        end

        local reel_offsets = e:get(components.reel_offset_component).reel_offsets
        while not self.should_skip do
            for _, frame in ipairs(frames) do
                if self.should_skip then
                    return;
                end

                local auto_component = e:get(components.auto_component)
                if auto_component and auto_component.is_auto then
                    self:skip();
                    return;
                end

                local payline = self.ingame.machine.config.paylines[frame.id]
                if payline == nil then
                    gamelib.log.error("没有找到赔付线 id:"..frame.id)
                    break;
                end

                if #reel_offsets ~= #payline then
                    gamelib.log.error("#reel_offsets ~= #payline ->"..gamelib.dump(reel_offsets).."::::"..gamelib.dump(payline))
                    break;
                end

                local line_indexes = {};
                for i, value in ipairs(reel_offsets) do
                    table.insert(line_indexes, value + payline[i]);
                end

                local active_indexes = {};
                for i, index in ipairs(line_indexes) do
                    if frame.indexes & (1<<(i-1)) > 0 then
                        table.insert(active_indexes, {x = i, y = index});
                    end
                end

                slotlib.line.clear();
                local drawer = self.ingame.machine:draw(line_indexes);
                local color = drawer.material.color;
                self.ingame.machine:deactive_all();
                local active_elements = self.ingame.machine:get_elements_xy(active_indexes);

                local original_parent = nil;
                if e:has(components.cover_symbol_component) then
                    local cover_symbol_component = e:get(components.cover_symbol_component)
                    for _, element in ipairs(active_elements) do
                        if original_parent == nil then
                            original_parent = element.transform.parent;
                        end
                        element:set_parent(cover_symbol_component.cover_parent);
                    end    
                end

                self.original_parent = original_parent;
                self.active_elements = active_elements;

                for _, element in ipairs(active_elements) do
                    set_box_color(color, element);
                    element:active(true);
                end

                for _, element in ipairs(active_elements) do
                    set_box_color(color, element);
                    element:perform();
                    self:wait(0.1);
                end

                self:wait(1);
                
                if original_parent then
                    for _, element in ipairs(active_elements) do
                        element:set_parent(original_parent);
                    end
                end
            end
        end
    end)
end

function show_result_system:skip()
    self.super.skip(self);
    slotlib.line.clear();

    if self.original_parent == nil or self.active_elements == nil then
        return;
    end

    for _, element in ipairs(self.active_elements) do
        element:set_parent(self.original_parent);
    end
end

function show_result_system:_finish()
    show_result_system.super._finish(self);
    if self.active_elements then
        for _, element in ipairs(self.active_elements) do
            element:active(false);
        end 
    end
end

return show_result_system